package com.endoc.news.fragment.base;

import android.text.TextUtils;

import androidx.lifecycle.ViewModel;

import com.endoc.news.fragment.base.preference.BasicDataPreferenceUtil;
import com.endoc.news.fragment.mvvm.model.IBaseModelListener;
import com.endoc.news.fragment.mvvm.model.PagingResult;
import com.endoc.news.utils.GenericUtils;

import com.orhanobut.logger.Logger;

import com.google.gson.Gson;
import org.json.JSONException;
import org.json.JSONObject;

import java.lang.ref.WeakReference;
import java.util.Calendar;
import java.util.List;

import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.disposables.Disposable;

//对数据进行操作,提供ViewModel需要的数据
public abstract class BaseMvvmModel<NETWORK_DATA, RESULT_DATA> implements MvvmDataObserver<NETWORK_DATA> {
    protected WeakReference<IBaseModelListener> weakReference;//设置界面,将数据返回给此接口
    protected boolean mIsPage;//是否分页
    protected int mInitPage;
    protected int mPage;
    protected boolean isLoading = false;//是否正在加载
    protected String mCacheSPKey;//缓存的key
    private String mApkPredefinedData;//默认显示的数据

    //设置弱引用,防止接口的界面已经挂了,而网络请求才返回,和界面交互的接口需要用软引用!!!!!!!
    public void registerModelListener(IBaseModelListener iBaseModelListener) {
        if (iBaseModelListener != null) {
            weakReference = new WeakReference(iBaseModelListener);
        }
    }

    //订阅集合
    CompositeDisposable compositeDisposable;

    //把订阅储存起来
    public void addDisposable(Disposable disposable) {
        if (disposable == null) {
            return;
        }
        if (compositeDisposable == null) {
            compositeDisposable = new CompositeDisposable();
        }
        compositeDisposable.add(disposable);
    }

    //取消,防止内存泄露
    public void cancel() {
        if (compositeDisposable != null && !compositeDisposable.isDisposed()) {
            compositeDisposable.dispose();
        }
    }

    public BaseMvvmModel(boolean isPage, String cacheSPKey,String apkPredefinedData, int... initPage) {
        mIsPage = isPage;
        mCacheSPKey = cacheSPKey;
        mApkPredefinedData =apkPredefinedData;
        if (initPage != null && initPage.length > 0) {
            mPage = mInitPage = initPage[0];//初始化第一次加载的页面
        } else {
            mInitPage = -1;
        }
    }

    public void refresh() throws Exception {
        if (weakReference == null)
            throw new Exception("没有设置IBaseModelListener对象");
        if (!isLoading) {//如果没有正在加载
            if (mIsPage) {//如果存在分页,那么需要记录第一次的位置
                mPage = mInitPage;
            }
            isLoading = true;
            load();
        }
        Logger.d("刷新了.........");
        //mBaseViewModels.clear();
        //load();
    }

    /**
     * @param networkData 从网络返回的原始数据,因为原始数据知道是什么类型,而加工后的数据实现了多态,集合中存的可能是不同的子类,导致无法序列化
     * @param resultData  加工后的数据
     */
    public void notifyListener(NETWORK_DATA networkData, RESULT_DATA resultData, boolean isFromCache) {
        IBaseModelListener iBaseModelListener = weakReference.get();
        if (iBaseModelListener != null) {
            if (mIsPage) {//如果分页
                //data是model层传入的list集合,不然传入此处会出错,PagingResult中的判断: isEmpty的判断是model的是否为null.而hasNextPage判断的是如果当前页还有数据,那么就默认还有下页,加载数据
                iBaseModelListener.success(this, resultData, new PagingResult(mPage == mInitPage, resultData == null && ((List) resultData).size() == 0, ((List) resultData).size() > 0));
                if (mPage == mInitPage && !isFromCache) {//表明当前是第一页,并且数据不来自缓存,才存起来
                    setCacheData(networkData);
                }
                if (((List) resultData).size() > 0) {//如果这次的数据还存在数据,那么就直接加++
                    mPage++;
                }
            } else {//否则不分页
                iBaseModelListener.success(this, resultData);
                if (!isFromCache) {//如果数据不来自缓存
                    setCacheData(networkData);
                }
            }
        }
        if (!isFromCache) {//如果数据不来自缓存,那么才说明网络请求已经完成了
            isLoading = false;
        }
    }

    //需要区分是否是分页加载的失败还是非分页加载的失败
    public void loadFail(Throwable throwable) {
        IBaseModelListener iBaseModelListener = weakReference.get();
        if (iBaseModelListener != null) {
            if (mIsPage) {//如果分页
                iBaseModelListener.fail(this, throwable, new PagingResult(mPage == mInitPage, true, false));
            } else {
                iBaseModelListener.fail(this, throwable);
            }
        }
        isLoading = false;
    }

    public void loadNextPage() throws Exception {
        if (weakReference == null)
            throw new Exception("没有设置IBaseModelListener对象");
        if (!isLoading) {
            isLoading = true;
            load();
        }
    }

    public abstract void load();

    //设置缓存
    public void setCacheData(NETWORK_DATA baseCacheData) {
        BaseCacheData<NETWORK_DATA> cacheData = new BaseCacheData<>();
        cacheData.timeMil = Calendar.getInstance().getTimeInMillis();//记录时间
        cacheData.cacheData = baseCacheData;//记录数据
        //存到sp中
        BasicDataPreferenceUtil.getInstance().setString(mCacheSPKey, new Gson().toJson(cacheData));
    }

    protected boolean isNeedToUpdate(long cachedTimeSlot) {
        return true;
    }

    //得到缓存
    public void getCacheData() {
        if (!isLoading) {
            isLoading = true;
            if (mCacheSPKey != null) {//如果需要缓存
                String saveDataToString = BasicDataPreferenceUtil.getInstance().getString(mCacheSPKey);//拿到缓存的值
                if (!TextUtils.isEmpty(saveDataToString)) {//如果存在缓存
                    //Logger.d(saveDataToString);
                    try {
                        //Caused by: java.lang.ClassCastException: org.json.JSONObject cannot be cast to com.google.gson.JsonElement

                        //NETWORK_DATA data = new Gson().fromJson(new JSONObject(saveDataToString).get("cacheData"), (Class<NETWORK_DATA>) GenericUtils.getGenericType(this));//反序列化

                        NETWORK_DATA data = new Gson().fromJson(new JSONObject(saveDataToString).getString("cacheData"), (Class<NETWORK_DATA>) GenericUtils.getGenericType(this));

                        if (data != null) {
                            //Logger.d(data);
                            onSuccess(data, true);
                        }
                        long timeSlot = Long.parseLong(new JSONObject(saveDataToString).getString("timeMil"));
                        if (isNeedToUpdate(timeSlot)) {
                            load();
                            return;
                        }
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                }
                //如果不存在缓存,那么使用默认缓存
                if(mApkPredefinedData != null) {
                    NETWORK_DATA savedData = new Gson().fromJson(mApkPredefinedData, (Class<NETWORK_DATA>) GenericUtils.getGenericType(this));
                    if(savedData != null) {
                        onSuccess(savedData, true);
                    }
                }
            }
            //然后加载数据
            load();
        }
    }




}
